package chap_05;

import chap_04.Dish;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * 查找和匹配
 * Stream API通过allMatch、anyMatch、noneMatch、findFirst和findAny方法提供了这样的工具
 */
public class Run_03 {
    List<Dish> menu = Arrays.asList(
            new Dish("pork", false, 800, Dish.Type.MEAT),
            new Dish("beef", false, 700, Dish.Type.MEAT),
            new Dish("chicken", false, 400, Dish.Type.MEAT),
            new Dish("french fries", true, 530, Dish.Type.OTHER),
            new Dish("rice", true, 350, Dish.Type.OTHER),
            new Dish("season fruit", true, 120, Dish.Type.OTHER),
            new Dish("pizza", true, 550, Dish.Type.OTHER),
            new Dish("prawns", false, 300, Dish.Type.FISH),
            new Dish("salmon", false, 450, Dish.Type.FISH));

    /**
     * 检查谓词是否至少匹配一个元素
     */
    @Test
    public void demo_01() {
        if (menu.stream().anyMatch(Dish::isVegetarian)) {
            System.out.println("The menu is (somewhat) vegetarian friendly!!");
        }

        Optional<Dish> any = menu.stream().filter(Dish::isVegetarian).findAny();
        if(any.isPresent()) {
            System.out.println(any.get());
        }
    }

    /**
     * 检查谓词是否匹配所有元素
     */
    @Test
    public void demo_02() {
        boolean isHealthy = menu.stream()
                .allMatch(d -> d.getCalories() < 1000);

        System.out.println(isHealthy);

        isHealthy = menu.stream()
                .noneMatch(d -> d.getCalories() >= 1000);

        System.out.println(isHealthy);

    }

    /**
     * findAny方法将返回当前流中的任意元素。它可以与其他流操作结合使用。
     * 比如，你可能想找到一道素食菜肴。你可以结合使用filter和findAny方法来实现这个查询
     */
    @Test
    public void demo_03() {
        menu.stream()
            .filter(Dish::isVegetarian)
            .findAny()
            .ifPresent(d -> System.out.println(d.getName()));
    }

    /**
     * 查找第一个元素
     */
    @Test
    public void demo_04() {
        List<Integer> someNumbers = Arrays.asList(1, 2, 3, 4, 5);
        Optional<Integer> firstSquareDivisibleByThree =
                someNumbers.stream()
                        .map(x -> x * x)
                        .filter(x -> x % 3 == 0)
                        .findFirst();  // 9

        firstSquareDivisibleByThree.ifPresent(d -> System.out.println(d));
    }
}
